package net.sk.china.platform.service.impl.city;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import net.sk.china.common.exception.TalkException;
import net.sk.china.common.request.PageParamRequest;
import net.sk.china.common.response.CommonPage;
import net.sk.china.common.utils.DateUtil;
import net.sk.china.common.utils.RedisUtil;
import net.sk.china.common.utils.TalkUtil;
import net.sk.china.platform.constants.Constants;
import net.sk.china.platform.dao.city.CityDao;
import net.sk.china.common.model.city.City;
import net.sk.china.common.model.system.SystemCity;
import net.sk.china.platform.request.city.CityAddRequest;
import net.sk.china.platform.request.city.CityRequest;
import net.sk.china.platform.request.city.CityRestPasswordRequest;
import net.sk.china.platform.request.city.CityUpdateRequest;
import net.sk.china.platform.response.city.CityResponse;
import net.sk.china.platform.service.city.CityService;
import net.sk.china.platform.service.system.SystemCityService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * CityServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2018-2024 聊来All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * +----------------------------------------------------------------------
 * | @Author: 聊来 <18970881148@qq.com>
 * +----------------------------------------------------------------------
 * | DateTime: 2024/6/11 15:40
 * +----------------------------------------------------------------------
 */

@Service
public class CityServiceImpl extends ServiceImpl<CityDao, City> implements CityService {

    @Resource
    private CityDao dao;

    private final SystemCityService systemCityService;

    private final RedisUtil redisUtil;

    public CityServiceImpl(SystemCityService systemCityService, RedisUtil redisUtil) {
        this.systemCityService = systemCityService;
        this.redisUtil = redisUtil;
    }

    /**
     * 列表
     * @param request 查询条件
     * @param page 分页
     * @return {@code PageInfo<CityResponse>}
     */
    @Override
    public PageInfo<CityResponse> getList(CityRequest request, PageParamRequest page) {
        Page<CityResponse> cityPage = PageHelper.startPage(page.getPage(), page.getLimit());

        LambdaQueryWrapper<City> query = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(request.getRoles())) {
            query.eq(City::getRoles, request.getRoles());
        }
        if (ObjectUtil.isNotNull(request.getStatus())) {
            query.eq(City::getStatus, request.getStatus());
        }
        if (StrUtil.isNotBlank(request.getKeywords())) {
            query.and(i -> i.like(City::getRealName, request.getKeywords())
                    .or().like(City::getName, request.getKeywords())
                    .or().like(City::getAccount, request.getKeywords()));
        }
        query.eq(City::getParentId, Constants.NUM_ZERO);
        query.select(City::getId, City::getName, City::getRealName, City::getAccount, City::getPhone, City::getLastIp, City::getStatus, City::getAreaCode,
                City::getRoles, City::getIndependent, City::getLoginCount, City::getCreateTime);
        List<City> cityList = dao.selectList(query);

        List<CityResponse> cityResponse = new ArrayList<>();
        for (City city : cityList) {
            CityResponse response = new CityResponse();
            BeanUtils.copyProperties(city, response);
            if (StrUtil.isBlank(city.getRoles())) { continue; }
            response.setCity(systemCityService.getCityByAreaCode(city.getAreaCode()));
            cityResponse.add(response);
        }
        return CommonPage.copyPageInfo(cityPage, cityResponse);
    }

    /**
     * 详情
     * @param id 数据ID
     * @return {@code City}
     */
    @Override
    public City getDetail(Integer id) {
        City city = dao.selectById(id);
        if (ObjectUtil.isNull(city)) {
            throw new TalkException("分站管理员不存在，请核实");
        }

        return city;
    }

    /**
     * 开启、关闭
     * @param id 数据ID
     * @param status 状态 true:开启 false:关闭
     * @return {@code boolean}
     */
    @Override
    public boolean updateStatus(Integer id, Boolean status) {
        if (ObjectUtil.isNull(status)) {
            throw new TalkException("状态码异常");
        }
        getDetail(id);

        UpdateWrapper<City> query = new UpdateWrapper<>();
        query.set("status", status);
        query.eq("id", id);

        return dao.update(null, query) >= 1;
    }


    /**
     * 重置密码
     * @param request 请求参数
     * @return {@code boolean}
     */
    @Override
    public boolean restPassword(CityRestPasswordRequest request) {
        if (!request.getPassword().equals(request.getCheckPassword())) {
            throw new TalkException("两次输入的密码不一致");
        }
        City city = getDetail(request.getId());

        UpdateWrapper<City> query = new UpdateWrapper<>();
        query.set("pwd", TalkUtil.encryptPassword(request.getPassword(), city.getAccount()));
        query.eq("id", request.getId());

        return dao.update(null, query) >= 1;
    }

    /**
     * 添加分站管理员
     * @param request 请求参数
     * @return {@code boolean}
     */
    @Override
    public boolean add(CityAddRequest request) {
        if (!request.getPwd().equals(request.getCheckPwd())) {
            throw new TalkException("两次输入的密码不一致");
        }
        // 分站超管账号唯一校验
        Long result = checkAccount(request.getAccount());
        if (result > 0) {
            throw new TalkException("该分站超管账号已存在");
        }

        SystemCity systemCity = systemCityService.getCityByCityId(request.getCityId());
        if (ObjectUtil.isNull(systemCity)) {
            throw new TalkException("你选择的城市不存在，请核实");
        }

        if (request.getIndependent().equals(Constants.NUM_ONE) && !systemCity.getLevel().equals(Constants.NUM_TWO)) {
            throw new TalkException("只有县区等级的账号，允许创建独立的小程序账号");
        }

        City cityInfo = dao.getCheckAreaCodeInfo(systemCity.getAreaCode());
        if (ObjectUtil.isNotNull(cityInfo)) {
            throw new TalkException("该分站下已存在超管账号，请选择其他城市");
        }


        City city = new City();
        BeanUtils.copyProperties(request, city);
        city.setPwd(TalkUtil.encryptPassword(request.getPwd(), request.getAccount()));
        city.setParentId(Constants.NUM_ZERO);
        city.setRoles("1");
        city.setAreaCode(systemCity.getAreaCode());
        city.setCreateTime(DateUtil.getNowTime());
        city.setUpdateTime(DateUtil.getNowTime());

        boolean res = dao.insert(city) >= 1;

        if (res && systemCity.getLevel().equals(Constants.NUM_TWO)) { redisUtil.hmSet(net.sk.china.common.constants.Constants.CITY_ACCOUNT, systemCity.getAreaCode(), city); }

        return res;
    }

    /**
     * 更新分站管理员
     * @param request 请求参数
     * @return {@code boolean}
     */
    @Override
    public boolean update(CityUpdateRequest request) {
        getDetail(request.getId());
        verifyAccount(request.getId(), request.getAccount());

        SystemCity systemCity = systemCityService.getCityByCityId(request.getCityId());
        if (ObjectUtil.isNull(systemCity)) {
            throw new TalkException("你选择的城市不存在，请核实");
        }

        if (request.getIndependent().equals(Constants.NUM_ONE) && !systemCity.getLevel().equals(Constants.NUM_TWO)) {
            throw new TalkException("只有县区等级的账号，允许创建独立的小程序账号");
        }

        City cityInfo = dao.getVerifyAreaCodeInfo(request.getId(), systemCity.getAreaCode());
        if (ObjectUtil.isNotNull(cityInfo)) {
            throw new TalkException("该分站下已存在超管账号，请选择其他城市");
        }
        City city = new City();
        BeanUtils.copyProperties(request, city);
        city.setParentId(Constants.NUM_ZERO);
        city.setRoles("1");
        city.setAreaCode(systemCity.getAreaCode());
        city.setUpdateTime(DateUtil.getNowTime());

        boolean res = dao.updateById(city) >= 1;

        if (res && systemCity.getLevel().equals(Constants.NUM_TWO)) { redisUtil.hmSet(net.sk.china.common.constants.Constants.CITY_ACCOUNT, systemCity.getAreaCode(), city); }

        return res;
    }

    /**
     * 分站超管账号唯一校验
     * @param account 账号
     * @return {@code Long}
     */
    private Long checkAccount(String account) {
        LambdaQueryWrapper<City> query = new LambdaQueryWrapper<>();
        query.eq(City::getAccount, account);

        return dao.selectCount(query);
    }

    /**
     * 校验账号唯一性（更新时）
     * @param id 数据ID
     * @param account 账号
     */
    public void verifyAccount(Integer id, String account) {
        LambdaQueryWrapper<City> query = new LambdaQueryWrapper<>();
        query.ne(City::getId, id);
        query.eq(City::getAccount, account);
        query.last("LIMIT 1");
        City city = dao.selectOne(query);
        if (ObjectUtil.isNotNull(city)) {
            throw new TalkException("该分站超管账号已存在");
        }
    }
}
